package com.healthdata.service.impl;

import com.healthdata.service.DataPreprocessService;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import weka.core.Attribute;
import weka.core.DenseInstance;
import weka.core.Instances;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class DataPreprocessServiceImpl implements DataPreprocessService{

    // 处理CSV文件，将CSV文件转换成Instances对象
    public Instances processCSV(MultipartFile file) throws IOException {
        //获取上传文件输入流
        InputStream is = file.getInputStream();
        //输入流包裹在BufferedReader中
        BufferedReader reader = new BufferedReader(new InputStreamReader(is));

        //创建CSV解析器                               CSV文件的第一行包含列名，作为每一列的标签
        CSVParser csvParser = new CSVParser(reader, CSVFormat.DEFAULT.withHeader());

        //创建属性列表
        ArrayList<Attribute> attributes = new ArrayList<>();
        //headerMap保存CSV列名和对应的列索引
        Map<String, Integer> headerMap = csvParser.getHeaderMap();
        //遍历遍历headerMap中的所有列名，为每一个列名创建一个Attribute对象，添加到列表中
        for (String header : headerMap.keySet()) {
            attributes.add(new Attribute(header));
        }
        //                             数据集名称，列名，数据集初始大小
        Instances data = new Instances("CSVData", attributes, 0);

        for (CSVRecord record : csvParser) {
            DenseInstance instance = new DenseInstance(attributes.size());
            for (String header : headerMap.keySet()) {
                instance.setValue(attributes.get(headerMap.get(header)), Double.parseDouble(record.get(header)));
            }
            data.add(instance);//将是列添加到data数据集中
        }

        csvParser.close();
        return data;
    }

    // 处理Excel文件
    public Instances processExcel(MultipartFile file) throws IOException {
        InputStream is = file.getInputStream();
        Workbook workbook = new XSSFWorkbook(is);
        Sheet sheet = workbook.getSheetAt(0);

        ArrayList<Attribute> attributes = new ArrayList<>();
        //读取表头
        Row headerRow = sheet.getRow(0);
        //逐列获取列名
        for (int i = 0; i < headerRow.getLastCellNum(); i++) {
            attributes.add(new Attribute(headerRow.getCell(i).getStringCellValue()));
        }

        //创建的是Instances，有s
        Instances data = new Instances("ExcelData", attributes, 0);

        //逐行读取数据
        for (int i = 1; i <= sheet.getLastRowNum(); i++) {
            Row row = sheet.getRow(i);
            //创建的是每一行instance,不带s，一行对应的数据存进大数据集中
            DenseInstance instance = new DenseInstance(attributes.size());
            for (int j = 0; j < row.getLastCellNum(); j++) {
                instance.setValue(attributes.get(j), row.getCell(j).getNumericCellValue());
            }
            data.add(instance);
        }

        workbook.close();
        return data;
    }

    // 处理JSON文件
    public Instances processJSON(MultipartFile file) throws IOException {

        //读取json文件内容
        String json = new String(file.getBytes());
        //使用Jackson解析JSON
        com.fasterxml.jackson.databind.ObjectMapper mapper = new com.fasterxml.jackson.databind.ObjectMapper();
        List<Map<String, Object>> jsonList = mapper.readValue(json, List.class);

        ArrayList<Attribute> attributes = new ArrayList<>();
        Map<String, Integer> attributeIndexMap = new HashMap<>();
        //读第一个对象的键，从而得到所有的属性名
        if (!jsonList.isEmpty()) {
            Map<String, Object> firstObject = jsonList.get(0);
            int index = 0;
            for (String key : firstObject.keySet()) {
                attributes.add(new Attribute(key));
                attributeIndexMap.put(key, index++);
            }
        }

        Instances data = new Instances("JSONData", attributes, 0);

        for (Map<String, Object> jsonObject : jsonList) {
            DenseInstance instance = new DenseInstance(attributes.size());
            for (String key : jsonObject.keySet()) {
                instance.setValue(attributes.get(attributeIndexMap.get(key)), Double.parseDouble(jsonObject.get(key).toString()));
            }
            data.add(instance);
        }

        return data;
    }

}
